use std::{env::{current_dir,set_current_dir},ops::Deref,path::PathBuf , sync::{Arc , atomic::{self,AtomicBool}}} ;

use arc_swap::ArcSwap;
use jizi_shared::{RoCell,url::Url} ;

pub struct Cwd(ArcSwap<Url>) ;
pub static CWD: RoCell<Cwd> = RoCell::new() ; // 其内部还是空的

impl Deref for Cwd{
    type Target = ArcSwap<Url> ;
    fn deref(&self) -> &Self::Target{&self.0} 
}

impl Default for Cwd{
    fn default() -> Self {
        let p = std::env::var_os("PWD")
        .map(PathBuf::from)
        .filter(|p| p.is_absolute())
        .or_else(||current_dir().ok())
        .expect("failed to get current working directory") ;
        
        Self(ArcSwap::new(Arc::new(Url::from(p))))
    }

}

impl Cwd{
    /// 设置当前工作目录
    pub fn set(&self, url : &Url) -> bool {
        if self.load().as_ref() == url {
            return false;
        }
        self.store(Arc::new(url.clone())) ;
        unsafe{
            std::env::set_var("PWD" , url) ; // url需要实现Asref
        }
        Self::sync_cwd() ;
        true 
    }
    /// 同步当前目录和CWD静态变量的值
    fn sync_cwd(){
        static SYNCING : AtomicBool = AtomicBool::new(false) ;
        if SYNCING.swap(true , atomic::Ordering::Relaxed){ // 先将此静态变量静态设置成true 返回false；其他线程也设置成true，但是返回了true，说明更新正在进行，进入代码块，直接返回
            return ;
        }
        // 启动一个后台执行同步操作
        tokio::task::spawn_blocking(move||{
            _ = set_current_dir(CWD.load().as_ref()) ; // 将当前工作目录设置为CWD
            let p = current_dir().unwrap_or_default() ;

            SYNCING.store(false , atomic::Ordering::Relaxed) ; 
            if p != CWD.load().as_path(){ // 检查是否设置成功
                set_current_dir(CWD.load().as_ref()).ok() ; // 如果不成功尝试再次设置
            }
        }) ; 
    }
}